<?php
/**
* 出入库单据相关处理
*/
class console_receipt_stock{
    private $_isoObj = null;

    private $_itemsObj = null;

    private $_isoInfo = array();

    private $_items = array();

    private static $iso_status =array(
        'PARTIN'=>2 ,
        'FINISH'=>3,
        'CLOSE'=>4,
        'CANCEL'=>4,
        'FAILED'=>4,
    );
    
    function __construct() {
        $this->_isoObj = app::get('taoguaniostockorder')->model("iso");
        $this->_itemsObj = app::get('taoguaniostockorder')->model("iso_items");
        $this->_branchLib = kernel::single('ome_branch');
    }

    /**
    * 出入库据保存
    * io 0 出库 1 入库
    * 入库会有残损
    * 出库不会
    * $array $data 
    */
    public function do_save($data,$io,&$msg){

       
        set_time_limit(0);
        $iostock_update = true;
        $io_status = $data['io_status'];
        $iostockData = $this->_format_items($data,$io,$iostock_update);
        if ($io=='0'){
            $stockLib = kernel::single('siso_receipt_iostock_stockout');
        }else{
            $stockLib = kernel::single('siso_receipt_iostock_stockin');
        }
        $stockLib->_typeId = $this->_isoInfo['type_id'];
       
        kernel::database()->exec('begin');
        if($iostockData['items']){
            $result = $stockLib->create($iostockData, $data, $msg);
            if (!$result){
                kernel::database()->exec('rollback');
                $msg = '出入库失败';
                return false;
            }
        }
        $io_update_data = array('iso_status'=>self::$iso_status[$io_status],'confirm'=>'Y');
        
        if (!$iostock_update){#是否需要确认
            $io_update_data['defective_status'] = '1';#未确认
            
        }
        #是否有备注
        if ($data['memo']){
            $memo = '';
            if (!$this->_isoInfo['memo']){
                $memo.= $_isoInfo['memo'];
            }
            $memo.=htmlspecialchars($data['memo']);
            $io_update_data['memo'] = $memo;
        }
        $iso_result = $this->_isoObj->update($io_update_data,array('iso_id'=>$this->_isoInfo['iso_id']));
        if (!$iso_result){
            kernel::database()->exec('rollback');
            $msg = '出入库单据状态更新失败';
            return false;
        }
        kernel::database()->exec('commit');
        if ($io=='0'){
            //减冻结
            $this->clear_stockout_store_freeze($iostockData,$io_status);
        }
        
        if ($this->_isoInfo['type_id'] == '4' && $io_status == 'FINISH') {
            $this->reduceArriveStore();
        }
       
        if ($this->_isoInfo['type_id']=='40' && $io_status == 'FINISH'){
            #调拔出库且为完成时执行调拔入库
            
            kernel::single('console_iostockdata')->allocate_out($this->_isoInfo['iso_id']);
        }
        return true;
        
    }
    
    

    /**
     *
     * 出入库单取消
     * @param $io_bn 出入库单号
     * @param $io 出 入标识
     */
    public function cancel($io_bn,$io){
       $result = $this->_isoObj->update(array('iso_status'=>'4'),array('iso_bn'=>$io_bn));
        //释放冻结库存
        $iostockdata= $this->_isoInfo;
        if ($io=='0'){
            
            $iostockdata['items'] = $this->_items;
            $this->clear_stockout_store_freeze($iostockdata);
            
        }
        //调拔入库取消在途
        if($iostockdata['type_id'] == '4'){
            $this->reduceArriveStore();
        }
        return $result;
    }

    
    
    /**
     * 检查传过来的货号是否都存在于单据中
     * @param iso_id 出入库单ID
     * @param items array 货品明细
     */
     public function checkBnexist($iso_id,$items){#taoguaniostockorder_iso
       
        $bn_array = array();
        foreach($items as $item){
            $bn_array[]=$item['bn'];
        }
        $bn_total = count($bn_array);

        $bn_array = '\''.implode('\',\'',$bn_array).'\'';
 
        $iso_items = $this->_isoObj->db->selectrow('SELECT count(iso_items_id) as count FROM sdb_taoguaniostockorder_iso_items WHERE iso_id='.$iso_id.' AND bn in ('.$bn_array.')');

       
        if ($bn_total!=$iso_items['count']){#比较数目是否相等
            return false;
        }
        return true;
    }

    /**
     *
     * 检查出入库单是否有效
     * @param  $iso_bn 出入库单编号
     * @param $status 需要执行状态
     * @msg 返回结果
     *
     */
    public function checkValid($iso_bn,$status,&$msg){
        $iso = $this->checkExist($iso_bn);
        if (!$iso){
            $msg = '单据号不存在!';
            return false;
        }
        $iso_status = $iso['iso_status'];

        switch($status){
            case 'PARTIN':
            case 'FINISH':
                if ($iso_status=='3'){
                    $msg = '单据已完成,不可以入库';
                    return false;
                }
                if ($iso_status == '4'){
                    $msg = '单据已取消，不可以入库';
                    return false;
                }
                break;
            case 'CANCEL':
            case 'CLOSE':
                if ($iso_status=='3' || $iso_status=='2'){

                    $msg = '单据已部分或全部入库,不可以取消';
                    return false;
                }
                if ($iso_status == '4'){
                    $msg = '单据已取消，不可以再次取消';
                    return false;
                }
                break;
        }
        return true;
    }

    /**
    * 释放冻结库存
    *
    * array data 当有明细时,操作对应明细，否则操作所有
    */
    public function clear_stockout_store_freeze($data,$io_status=''){
        $basicMaterialStock    = kernel::single('material_basic_material_stock');
        $libBranchProduct    = kernel::single('ome_branch_product');
        $branch_id = $data['branch_id'];
        $_items = $this->_items;
        $productBns = array();
        $items = $data['items'];
       foreach((array)$items as $item){
            if ($item['nums']<=0) continue;
            $effective_num = isset($item['effective_num']) ? $item['effective_num'] : ($item['nums']-$item['normal_num']);
            $num = 0;
            if ($io_status == 'FINISH' || $io_status == ''){
                $num = $effective_num;
            }else{
                $num = $effective_num>0 ? $item['nums'] : $effective_num;
            }
            
            $product_id = $item['product_id'];
            
            if ($num>0){
                $productBns[$item['bn']] = $item['bn'];
                $basicMaterialStock->chg_product_store_freeze($product_id, $num, '-', 'other');
                $libBranchProduct->chg_product_store_freeze($branch_id, $product_id, $num, '-', 'other');
            }
            
       }
       //当状态为全部完成时需将未产生过出入库记录释放冻结
        if($io_status == 'FINISH'){
            
            $iostock_list = $this->getIostockList($this->_isoInfo['type_id'],$data['iso_id']);
            foreach ($_items as $_item){
                $num = 0;
                if($_item['normal_num']==0 && !in_array($_item['bn'],$iostock_list)){
                    $num = $_item['nums']-$_item['normal_num'];
                    
                }
                //处理之前部分出库
                if(($_item['normal_num']>0 && $_item['nums']>$_item['normal_num']) && in_array($_item['bn'],$iostock_list) && (in_array($_item['bn'],$productBns)==false)){

                    $num = $_item['nums']-$_item['normal_num'];
                    
                }
                if ($num>0){
                    $basicMaterialStock->chg_product_store_freeze($_item['product_id'], $num, '-', 'other');
                    $libBranchProduct->chg_product_store_freeze($branch_id, $_item['product_id'], $num, '-', 'other');
                }

            }
        }
    }

     /**
    * 判断出入库明细是否存在
    *
    */
    public function checkExist($io_bn){
        
        $iso = $this->_isoObj->dump(array('iso_bn'=>$io_bn),'*');
        if ($iso){
            $this->_isoInfo = $iso;

            $iso_id = $iso['iso_id'];
            $_items = $this->_itemsObj->getList('iso_id,iso_items_id,defective_num,normal_num,nums,price,product_id,bn',array('iso_id'=>$iso_id));
            $this->_items= array();
            foreach ($_items as $k=>$item){
                $this->_items[$item['bn']] = $item;
            }
        }
        
        return $iso;
        
    }

    /**
    * 查看差异数据
    */
    function difference_stock($iso_bn){
      
        $iso = $this->_isoObj->dump(array('iso_bn'=>$iso_bn),'iso_id');
        $iso_id = $iso['iso_id'];
        
        $sql = 'SELECT i.nums,i.normal_num,i.defective_num,i.bn, p.material_name AS name FROM sdb_taoguaniostockorder_iso_items as i 
                LEFT JOIN sdb_material_basic_material as p ON i.bn=p.material_bn 
                WHERE i.iso_id='.$iso_id.' AND (i.normal_num!=i.nums OR i.defective_num>0)';
        
        $iso_item = $this->_isoObj->db->select($sql);
        return $iso_item;
    }

   

    function _format_items($data,$io,&$iostock_update){

        $items = array();
        $iostock = array(
            'iso_id'=>$this->_isoInfo['iso_id'],
            'type_id'=>$this->_isoInfo['type_id'],
            'iso_bn'=>$this->_isoInfo['iso_bn'],
            'memo'=>$data['memo'],
            'operate_time'=>$data['operate_time'],
            'branch_id'=>$this->_isoInfo['branch_id'],
        );

        foreach ($data['items'] as $item){

            $num = $io == '0' ? intval($item['num']) : intval($item['normal_num']);
            
            if ($this->_items[$item['bn']]){
                $itemdata = array();
                if ($num>0){
                    $itemdata['normal_num'] = $this->_items[$item['bn']]['normal_num']+$num;
                    $effective_num = $this->_items[$item['bn']]['nums']-$this->_items[$item['bn']]['normal_num'];
                }
                if ($item['defective_num']>0){
                    $itemdata['defective_num'] = $this->_items[$item['bn']]['defective_num']+$item['defective_num'];
                    $iostock_update = false;
                }
                
                $this->_itemsObj->update($itemdata,array('iso_items_id'=>$this->_items[$item['bn']]['iso_items_id'],'iso_id'=>$this->_items[$item['bn']]['iso_id']));
                $items[] = array(
                    'bn'=>$item['bn'],
                    'nums'=>$num,#请求入库数量
                    'price'=>$this->_items[$item['bn']]['price'],
                    'iso_items_id'=>$this->_items[$item['bn']]['iso_items_id'],
                    'product_id'=>$this->_items[$item['bn']]['product_id'],
                    'effective_num'=>$effective_num,
                
                );
            }

        }
        $iostock['items'] = $items;

        return $iostock;
    
    }

    

    
    /**
     * 调拨入库扣除在途库存
     *
     * @return void
     * @author 
     **/
    private function reduceArriveStore()
    {
        $iso = $this->_isoInfo;
        $items = $this->_items;
        $libBranchProduct    = kernel::single('ome_branch_product');
        foreach ($items as $item) {
            $libBranchProduct->change_arrive_store($iso['branch_id'], $item['product_id'], $item['nums'],'-');
        }
    }

    function getIostockList($type_id,$iso_id){
        $db = kernel::database();
        $sql = "SELECT bn FROM sdb_ome_iostock WHERE type_id in(".$type_id.") AND original_id=".$iso_id;
        $items = array();
        $iso = $db->select($sql);
        foreach ($iso as $v){
            $items[]=$v['bn'];
        }
        return $items;
    }
}
    

?>